package edu.uestc.canary.commons.files.service.support;

import edu.uestc.canary.commons.files.config.MinioConfigProperties;
import edu.uestc.canary.commons.files.exception.NotSupportFileContentTypeException;
import edu.uestc.canary.commons.files.service.FileService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

@Service
@Slf4j
public class FileServiceBean implements FileService {
    @Resource private MinioClient client;
    @Resource private MinioConfigProperties properties;

    //文件夹分隔符
    private static final char SEPARATOR = '/';
    @Override
    public String uploadImgFile(String contentType, String filename, InputStream inputStream) {
        try {
            //上传非图片内容，扔出自定义异常,结束业务
            if(contentType == null || !contentType.startsWith("image/"))
                throw new NotSupportFileContentTypeException("仅支持上传图片文件：" + contentType);

            var filepath = buildFilePath(filename);
            var parameter = PutObjectArgs.builder()
                    .object(filepath)
                    .contentType(contentType)
                    .bucket(properties.getBucket())
                    .stream(inputStream, inputStream.available(), -1)
                    .build();
            client.putObject(parameter);
            //http://192.168.254.188:9000/canary-images/tiantian/2023/09/11/sufei.jpg
            return properties.getEndpoint() + SEPARATOR + properties.getBucket() + SEPARATOR + filepath;
        } catch (Exception e) {
            log.error("上传图片失败:{}",e.getMessage(),e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public String uploadHtmlFile(String filename, InputStream inputStream) {
        try {
            var filepath = buildFilePath(filename);
            var parameter = PutObjectArgs.builder()
                    .object(filepath) //文件名
                    .bucket(properties.getBucket()) //桶名称
                    .contentType("text/html") //文件类型
                    .stream(inputStream, inputStream.available(), -1)
                    .build();
            client.putObject(parameter);
            return properties.getEndpoint() + SEPARATOR + properties.getBucket() + SEPARATOR + filepath;
        } catch (Exception e) {
            log.error("上传html文件失败:{}",e.getMessage(),e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public void delete(String path) {
        try {
            var parameter = RemoveObjectArgs.builder()
                    .bucket(properties.getBucket())
                    .object(path)
                    .build();
            client.removeObject(parameter);
        } catch (Exception e) {
            log.error("删除文件失败,file path:{}",path,e);
        }
    }

    @Override
    public byte[] downLoadFile(String path) {
        try {
            var parameter = GetObjectArgs.builder()
                    .bucket(properties.getBucket())
                    .object(path)
                    .build();
            var object = client.getObject(parameter);
            var out = new ByteArrayOutputStream();
            var buff = new byte[1024 * 8];
            var len = -1;
            while((len = object.read(buff)) != -1)
                out.write(buff, 0, len);
            return out.toByteArray();
        } catch (Exception e) {
            log.error("文件下载失败，file path:{}",path,e);
        }
        return new byte[0];
    }

    /**
     * 构建文件完整路径
     * @param filename 文件名
     * @return canary/yyyy/MM/dd/filename
     */
    private String buildFilePath(String filename) {
        //canary/2023/09/11/sufei.jpg
        var sb = new StringBuilder();
        if(StringUtils.hasLength(properties.getReadPath()))
            sb.append(properties.getReadPath()).append(SEPARATOR);
        var date = DateTimeFormatter.ofPattern("yyyy/MM/dd").format(LocalDate.now());
        sb.append(date).append(SEPARATOR).append(filename);
        return sb.toString();
    }
}
